import axios from 'axios';
import { v4 as uuidv4 } from 'uuid';
import { AuthProvider, findOrCreateUser, findOrCreateWechatopenUser } from '../../../services/uctoo/uctoo_user';
import { WechatUser } from '../../../services/uctoo/uctoo_user.types';
import { pushDiscordWebhook } from '../../../helpers/pushDiscordWebhook';
import { authorizeAndEnd, authorizeWechatuserAndEnd } from '../../../helpers/authorizeAndEnd';
import { defaultRouteHandler } from '../../../../interfaces';
import log from '../../../helpers/logger';
import { getFirstWechatopenFromDatabase } from '../../../services/uctoo/wechatopen';
import { queryAdminAppletsFromDatabase } from '../../../services/uctoo/admin_applet';
import {  queryWechatopenAppletsFromDatabase } from '../../../services/uctoo/wechatopen_applet';
import { OfficialAccount, ServerRequest, FormData, defineOfficialAccountConfig, defineOpenPlatformConfig, OpenPlatform } from 'node-easywechat';
import db from '../../../lib/db';
import DbCacher  from '../../../lib/DbCacher';
import { dateToTimestampWithTimezone } from '../../../helpers/utilsJS';
import { webSocketStore } from '../../../websocket/websocket-store';

const { FRONTEND_URL } = process.env;

//Dictionary for request state checks
const stateDict = {};
const env = process.env.NODE_ENV;
const isDev = env === 'development';
class WechatopenAuthController {
  //Route for Oauth login with github
  public oauthRedirect: defaultRouteHandler = async (req, res) => {
    const { appid, redirect_scene, scope, client_id} = req.query;
    const url = 'https://open.weixin.qq.com/connect/oauth2/authorize';
    const wechatopenFromDb = await getFirstWechatopenFromDatabase({status:1},{id:'desc'});
    // 取出 wechatopen_applet数据
   // const adminApplet = await queryAdminAppletsFromDatabase(1, 0, { status: 1 });
   // if (!adminApplet) return res.status(404).end();
    //log.info('adminApplet:', adminApplet);
    const params: Record<string, any> = {};
    params.filter = JSON.stringify({ appid: appid });
    const wechatApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, params);
    if (!wechatApplet) return res.status(404).end();
    const redirectUrls = JSON.parse(wechatApplet[0].redirect_url);
    const redirectUrl = redirectUrls[String(redirect_scene)];
    log.info(client_id);
    log.info('oauthRedirect');
    log.info(redirectUrl);
    const body = {
      appid: wechatApplet[0].appid,
      redirect_uri: redirectUrl ,
      response_type: "code",
      scope: scope? String(scope) : "snsapi_base",
      state: client_id? String(client_id) : "wechat_H5",
      component_appid: wechatopenFromDb['appid'],
    };
    //scope=snsapi_base&state=wechatMenu&component_appid
    const qs = new URLSearchParams(body);
    const oauthUrl = `${url}?${qs}#wechat_redirect`;

    //return res.redirect(oauthUrl);
  /*  const wechatOauth = await axios
      .get(oauthUrl, {
        maxRedirects: 0, // 设置为0以阻止重定向
        validateStatus: null // 允许所有状态码通过
      })
      .then(response => {
        log.info('Status:', response.status);// 打印响应状态码
        if (response.status === 302) {
          // 如果是重定向，则会打印重定向的location
          log.info('Redirect Location:', response.headers.location);
        }
      })
      .catch(error => {
        log.info('Redirect error:', error);
      });
      log.info('wechatOauth:', wechatOauth); */
    return res.status(200).json({oauthUrl:oauthUrl});
  };

  
  //Route for Oauth login callback
  //handle cancelation + token requesting
  public oauthCallback: defaultRouteHandler = async (req, res) => {
    const reqbody = await req.json();
    log.info(reqbody);
    const { appid, code, state } = reqbody;
    log.info('reqbody');
        log.info(appid);
        log.info(code);
        log.info('state');
        log.info(state);
    //If wechat user cancels auth
    if (!code) {
      //redirect to app
      res.redirect(FRONTEND_URL);
    }

    //Check state parameter in case of cross-forgery attempt
  /*   if (!stateDict[state as string]) {
      res.send('State diff, possible cross-forgery attempt');
    }
    //Delete unused memory
    delete stateDict[state as string]; 
  */
    const opts = { headers: { accept: 'application/json' } };
    //通过 code 换取 access_token
    try {
      //https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Before_Develop/Official_Accounts/official_account_website_authorization.html

    /* const tokenBundle = await axios
        .post('https://github.com/login/oauth/access_token', body, opts)
        .then((_res) => _res.data); */

        //https://api.weixin.qq.com/sns/oauth2/component/access_token?appid=APPID&code=CODE&grant_type=authorization_code&component_appid=COMPONENT_APPID&component_access_token=COMPONENT_ACCESS_TOKEN
        const url = 'https://api.weixin.qq.com/sns/oauth2/component/access_token';
        const wechatopenFromDb = await getFirstWechatopenFromDatabase({status:1},{id:'desc'});
        const wechatopenConfig = defineOpenPlatformConfig({
          // 微信公众号的 app key
          app_id: wechatopenFromDb['appid'],
          // 微信公众号的 app secret
          secret: wechatopenFromDb['appsecret'],
          // 微信公众号的 token
          token: wechatopenFromDb['token'],
          // EncodingAESKey
          aes_key: wechatopenFromDb['encoding_aes_key'],
        
        })
        const wxopen = new OpenPlatform(wechatopenConfig);
       // const cat = wxopen.getComponentAccessToken();
       // wxopen.setComponentAccessToken();
       // log.info({ info: 'cat', cat });
        
        // 替换缓存实例
        let Dbcacher = new DbCacher(db);
        wxopen.setCache(Dbcacher);
        //在通知方法中已经维护了component_access_token生命周期，这里可以无需判断过期直接用
        const component_access_token = await wxopen.getComponentAccessToken().getToken();
        // 取出 wechatopen_applet数据
       // const adminApplet = await queryAdminAppletsFromDatabase(1, 0, { status: 1 });
       // if (!adminApplet) return res.status(404).end();
        //log.info('adminApplet:', adminApplet);
        const params: Record<string, any> = {};
        params.filter = JSON.stringify({ appid: appid });
        const wechatApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, params);
        if (!wechatApplet) return res.status(404).end();
    
        const body = {
          appid: wechatApplet[0].appid,
          code: String(code),
          grant_type: "authorization_code",
          component_appid: wechatopenFromDb['appid'],
          component_access_token: component_access_token,
        };
        //
        log.info(body);
        const qs = new URLSearchParams(body);
        const tokenUrl = `${url}?${qs}`;
        log.info('tokenUrl');
        log.info(tokenUrl);
        //return  res.status(200).json({tokenUrl:tokenUrl});
        const wechatUser = (await axios
          .get(tokenUrl)
          .then((_res) =>{ 
            log.info('_res:');
        log.info(_res);
          return  _res.data
          })) //res.redirect(tokenUrl);
        log.info('wechatUser:');
        log.info(wechatUser);
        if(wechatUser['scope'] == "snsapi_userinfo"){  //显式授权登录,一起获取用户资料
          const infoUrl = 'https://api.weixin.qq.com/sns/userinfo';

          const body = {
            access_token: wechatUser['access_token'],
            openid: wechatUser['openid'],
            lang: "zh_CN"
          };
        //
          log.info(body);
          const qs = new URLSearchParams(body);
          const userInfoUrl = `${url}?${qs}`;
          log.info('userInfoUrl');
          log.info(userInfoUrl);
        //return  res.status(200).json({tokenUrl:tokenUrl});
          const wechatUserInfo = (await axios
            .get(userInfoUrl)
            .then((_res) =>{ 
              log.info('_res:');
          log.info(_res);
            return  _res.data
            })) //res.redirect(tokenUrl);

            const wUser = {
              openid: wechatUser['openid'],
              access_token: wechatUser['access_token'],
              expires_in: wechatUser['expires_in'],
              refresh_token: wechatUser['refresh_token'],
              scope: wechatUser['scope'],
              name: wechatUser['openid'],
              username: wechatUser['openid'],
              email: wechatUser['openid'] + '@' + wechatApplet[0].appid + '.com',
              appid: wechatApplet[0].appid,
              nickname: wechatUserInfo['nickname'],
              gender: wechatUserInfo['sex'],         //sex
              province: wechatUserInfo['province'],
              city: wechatUserInfo['city'],
              country: wechatUserInfo['country'],
              avatar_url: wechatUserInfo['headimgurl'],     //headimgurl
              privilege: JSON.stringify(wechatUserInfo['privilege']),
              unionid: wechatUserInfo['unionid']
            };
            log.info('wUser', wUser);
            log.info(AuthProvider.Wechat);
      
            const user = await findOrCreateWechatopenUser(wUser, AuthProvider.Wechat);
            log.info('user');
            log.info(user);
            return authorizeWechatuserAndEnd(user, req, res, AuthProvider.Wechat);


        }else{                                //静默登录
          const wUser = {
            openid: wechatUser['openid'],
            access_token: wechatUser['access_token'],
            expires_in: wechatUser['expires_in'],
            refresh_token: wechatUser['refresh_token'],
            scope: wechatUser['scope'],
            name: wechatUser['openid'],
            username: wechatUser['openid'],
            email: wechatUser['openid'] + '@' + wechatApplet[0].appid + '.com',
            appid: wechatApplet[0].appid
          };
          log.info('wUser', wUser);
          log.info(AuthProvider.Wechat);
    
          const user = await findOrCreateWechatopenUser(wUser, AuthProvider.Wechat);
          log.info('authuser');
          log.info(user);
          //如果state参数是以login_client_id_开头，则为扫码登录用户，应用微信帐号关联的uctoo_user帐号授权登录，并websocket通知client_id扫码登录结果
          if(state.startsWith("login_client_id_")){
            log.info('login_client_id_');
            return authorizeWechatuserAndEnd(user, req, res, AuthProvider.Wechat, state);
          }else{ //微信帐号登录
            log.info('Wechatauthuser');
            return authorizeWechatuserAndEnd(user, req, res, AuthProvider.Wechat);
          }

          
        }  
      
    } catch (e) {
      res.json({ err: e.message });
    }
  };

  // 解密微信绑定手机号
  public decryptPhoneNumber: defaultRouteHandler = async (req, res) => {
    try {
      const { encryptedData, iv, sessionKey, appid } = await req.json();
      
      if (!encryptedData || !iv || !sessionKey || !appid) {
        return res.status(400).json({ err: '缺少必要参数' });
      }
      
      // 获取微信开放平台配置
      const wechatopenFromDb = await getFirstWechatopenFromDatabase({ status: 1 }, { id: 'desc' });
      if (!wechatopenFromDb) {
        return res.status(404).json({ err: '未找到微信开放平台配置' });
      }
      
      // 解密手机号
      const wechatopenConfig = defineOpenPlatformConfig({
        app_id: wechatopenFromDb['appid'],
        secret: wechatopenFromDb['appsecret'],
        token: wechatopenFromDb['token'],
        aes_key: wechatopenFromDb['encoding_aes_key'],
      });
      
      const wxopen = new OpenPlatform(wechatopenConfig);
      const dbCacher = new DbCacher(db);
      wxopen.setCache(dbCacher);
      
      // 使用微信开放平台SDK解密手机号
      // 注意：这里需要根据node-easywechat库的实际API调整解密方法
      let decryptedData;
      try {
        // 示例代码，实际解密方法可能不同
        const crypto = require('crypto');
        const sessionKeyBuffer = Buffer.from(sessionKey, 'base64');
        const encryptedDataBuffer = Buffer.from(encryptedData, 'base64');
        const ivBuffer = Buffer.from(iv, 'base64');
        
        const decipher = crypto.createDecipheriv('aes-128-cbc', sessionKeyBuffer, ivBuffer);
        decipher.setAutoPadding(true);
        decryptedData = JSON.parse(decipher.update(encryptedDataBuffer, 'binary', 'utf8') + decipher.final('utf8'));
        
        // 验证解密数据的appid
        if (decryptedData.watermark.appid !== appid) {
          return res.status(400).json({ err: '解密数据验证失败' });
        }
      } catch (error) {
        log.error('解密失败:', error);
        return res.status(500).json({ err: '解密失败', desc: error.message });
      }
      
      return res.status(200).json({ 
        success: true, 
        phoneNumber: decryptedData.phoneNumber 
      });
    } catch (e) {
      log.error('解密手机号异常:', e);
      return res.status(500).json({ err: e.message, desc: e });
    }
  };
}

export default WechatopenAuthController;
